﻿using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Three;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using QdArch.ThreeUtils;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Xml.Resolvers;
using Shape = LightCAD.Three.Shape;

namespace QdArch
{
    public partial class WallAction
    {
        public override BufferGeometry[] CreateGeometry3D(LcElement element, Matrix3d matrix)
        {
            var wall = element as QdWall;
            var wallLine = wall.BaseLine;
            var wallBot = wall.Bottom;
            var start = (wallLine.Start).ToThree(wallBot);
            var end = (wallLine.End).ToThree(wallBot);
            var lineVec = new Vector3().subVectors(end, start);
            var wallLen = lineVec.length();
            var wallHeight = wall.Height;
            var wallWidth = wall.Width;
            var wallWidthHlf= wallWidth/2;
            var xAxis = lineVec.clone().normalize();
            var yAxis = VectorUtil.ZAxis.clone();
            var zAxis = new Vector3().crossVectors(xAxis,yAxis).normalize();
            var coodMat = new Matrix4();
            coodMat.makeBasis(xAxis, yAxis, zAxis);
            coodMat.setPosition(start);
            var start2 = new Vector2(start.x, start.y);
            var wallAxis2 = new Vector2(xAxis.x, xAxis.y);
            Shape getWallRect(Vector2d wStart,Vector2d wEnd) 
            {
                var minx= wStart.ToThree().sub(start2).dot(wallAxis2);
                var maxx = wEnd.ToThree().sub(start2).dot(wallAxis2);
                return ShapeUtil.Rect(minx, 0, maxx, wallHeight);
            }
            //var wallShape2 = Rect(0, 0, wallLen, wallHeight);
            Vector2d ls ,le,rs,re;
            //wall.Points[0].ToThree().cross(wallAxis2)
            if (Vector2d.Cross(wallLine.End- wallLine.Start, wall.Points[0] - wallLine.Start) < 0)
            {
                ls = wall.Points[3];
                le = wall.Points[2];
                rs = wall.Points[0];
                re = wall.Points[1];
            }
            else 
            {
                ls = wall.Points[0];
                le = wall.Points[1];
                rs = wall.Points[3];
                re = wall.Points[2];
            }
            var frontShape2 = getWallRect(rs, re);
            var backShape2 = getWallRect(ls, le);
            
            if (wall.AssociateElements.Count > 0)
            {
                for (int i = 0; i < wall.AssociateElements.Count; i++)
                {
                    var assEle = wall.AssociateElements[i];
                    var qdEle = assEle.Element;
                    double holeBot=0, holeHeight=0;
                    Vector2d sp=new Vector2d(),ep=new Vector2d();
                    if (qdEle is QdDoorRef)
                    {
                        var door = (QdDoorRef)qdEle;
                        sp = door.StartPoint;
                        ep = door.EndPoint;
                        holeBot = door.Bottom;
                        holeHeight = door.Height;
                    }
                    else if (qdEle is QdWindowRef)
                    {
                        var window = (QdWindowRef)qdEle;
                        sp = window.StartPoint;
                        ep = window.EndPoint;
                        holeBot = window.Bottom;
                        holeHeight = window.Height;
                    }
                    else
                        continue;
                    var ds2 = sp.ToThree();
                    var de2 = ep.ToThree();
                    var sx = ds2.sub(start2).dot(wallAxis2);
                    var ex = de2.sub(start2).dot(wallAxis2);
                    var miny = Math.Max(holeBot - wall.Bottom, 0);
                    var maxy = holeHeight + miny;
                    if (sx > ex)
                    {
                        var temp = sx;
                        sx = ex;
                        ex = temp;
                    }
                    var shape = ShapeUtil.Rect(sx, miny, ex, maxy);
                    frontShape2.holes.push(shape);
                    backShape2.holes.push(shape);
                }
            }
            var frontShape = new CoordShape3(frontShape2, coodMat, wallWidthHlf);
            var backShape = new CoordShape3(backShape2, coodMat, -wallWidthHlf);
            var geoData = GeoUtil.GetMappedShapeGeometryData(frontShape, backShape);
            var geo = geoData.GetBufferGeometry();
            geo.computeVertexNormals();

            return new BufferGeometry[] { geo };
        }
        
    }
}